Lorsque vous voudrez créer une application, vous voudrez mettre plus qu'un seul widget dans une fenêtre. Notre premier exemple "hello world" utilise seulement un widget et on pouvait simplement utiliser set pour spécifier le containerChild widget pour window, ou utiliser containerAdd
pour "empaqueter" le widget dans la fenêtre. Mais lorsque vous voudrez mettre plus qu'un seul widget dans une fenêtre, comment contrôler où ces widgets seront positionnés? C'est là qu'intervient : l'empaquetage.
La plupart des empaquetages sont réalisés en créant des boites. Ce sont des widgets "conteneurs" invisibles que l'on peut remplir avec nos widgets et qui sont disponibles sous deux formes: une boite horizontale ou verticale. Lorsque l'on empaquette les widgets dans une boite horizontale, les objets sont insérés de gauche à droite ou de droite à gauche suivant l'appel utilisé. Dans une boite verticale, les widgets sont empaquetés du haut vers le bas ou inversement. On peut utiliser n'importe quelle combinaison de boites à l'intérieur ou à l'extérieur d'autres boites pour créer l'effet désiré.
Pour créer une boite horizontale, on utilise hBoxNew
, et pour une boite verticale vBoxNew
. Chaque fonction prend comme argument un Bool
et un Int
. Le premier paramètre donne à tous les enfants un espacement égal s’il est défini à True et le deuxième donne l'espace en pixels par défaut entre les enfants.
Les fonctions boxPackStart
et boxPackEnd sont utilisées pour placer des objets à l'intérieur de ces conteneurs. La fonction boxPackStart
commence en haut et va vers le bas dans une VBox
, commence à gauche et va vers la droite dans une HBox
. L'utilisation de ces fonctions permet de justifier à droite ou à gauche et peuvent être combinées de n'importe quelle manière pour obtenir l'effet escompté. Dans la plupart des exemples, nous utiliserons boxPackStart.
Un objet peut être un autre conteneur ou un widget. Dans la réalité, beaucoup de widgets sont des conteneurs eux-mêmes, comme button, mais on utilise généralement seulement un label à l'intérieur d'un button.
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
hbox <- hBoxNew True 10
button1 <- buttonNewWithLabel "Button 1"
button2 <- buttonNewWithLabel "Button 2"
set window [windowDefaultWidth := 200, windowDefaultHeight := 200,
containerBorderWidth := 10, containerChild := hbox]
boxPackStart hbox button1 PackGrow 0
boxPackStart hbox button2 PackGrow 0
onDestroy window mainQuit
widgetShowAll window
mainGUI
En utilisant boxPackStart
ou boxPackEnd
, Gtk sait où vous voulez placer votre widget, il peut alors modifier leur taille automatiquement et d'autres choses sympathiques.
boxPackStart :: (WidgetClass child, BoxClass self) => self -> child -> Packing -> Int -> IO ()
boxPackEnd :: (WidgetClass child, BoxClass self) => self -> child -> Packing -> Int -> IO ()
Le paramètre Packing
spécifie la façon dont les widgets dans le conteneur se comportent quand la fenêtre est redimensionnée. PackNatural
signifie que les widgets garderont leur taille et resteront ou ils se trouvent, PackGrow
signifie qu'ils seront redimensionnés, et PackRepel
signifie que les widgets seront également répartis des deux cotés. Le dernier paramètre est un Int qui spécifie l'espace additionnel à mettre entre cet enfant et ses voisins.
Notez que Packing s'applique uniquement à la dimension de la boite. Si, par exemple, vous spécifiez PackNatural
au lieu de PackGrow
dans l'exemple ci-dessus, le redimensionnement horizontal gardera les boutons à leur place originale, mais le redimensionnement vertical va changer la taille des boutons. Ceci est dû au fait que les boutons sont placés de façon homogène dans la boite horizontale (Le premier paramètre est True) et la boite elle-même sera redimensionnée avec la fenêtre. L'exemple qui va suivre montrera cela de façon plus claire.